package com.example.javabasic.thread.classone.threadpool;

import java.util.*;
import java.util.stream.IntStream;

/**
 * 自定义线程池2
 */
public class CustomPool extends Thread {
    //线程池状态为启动或者停止  true :启动状态,false: 停止状态
    private volatile boolean poolStatus = true;
    //自定义线程自增id;
    private static volatile int id = 0;
    //定义线程名称前缀
    private static String threadName = "CustomThread-";
    //定义线程组 使线程都在同一个线程组
    private ThreadGroup group = new ThreadGroup("CustomGroup");
    //定义Runnable 任务队列
    private static final Queue<Runnable> RUNNABLE_QUEUE = new ArrayDeque<>();
    //定义定长线程集合,这里使用Thread类的子类
    private static final List<TaskThread> POOL = new ArrayList<>();
    //定义最小线程数量
    private static int min;
    //最小线程数
    private static int max;

    //重写run方法
    @Override
    public void run() {
        while (poolStatus) {
            System.out.printf("Pool:Min:%d,Max:%d,poolSize:%d,RunnableSize:%d\n", min, max, POOL.size(), RUNNABLE_QUEUE.size());
            try {
                Thread.sleep(500);
                //如果任务数大于active && size< active
                if (RUNNABLE_QUEUE.size() > POOL.size() && POOL.size() < max) {
                    //往线程队列中添加线程
                    for (int i = POOL.size(); i < max; i++) {
                        if (POOL.size() < max) {
                            createTask();
                            System.out.println("线程 +1");
                        }
                    }
                }
                //当任务比线程数少的时候  且 线程数大于min
                if (RUNNABLE_QUEUE.size() < POOL.size() && POOL.size() > min) {
                    Iterator<TaskThread> iterator = POOL.iterator();
                    while (iterator.hasNext()) {
                        TaskThread next = iterator.next();
                        if (next.status == Status.BLOCKED && POOL.size() > min) {
                            //当线程处于阻塞状态的时候 尝试关闭线程
                            next.close();
                            iterator.remove();
                            System.out.println("线程 -1");
                        }
                    }
                }

            } catch (InterruptedException e) {
                poolStatus = false;
            }
        }
    }

    //无参构造
    public CustomPool() {
        this(2, 10, threadName);
    }


    //无参构造
    public CustomPool(int min, int max, String threadName) {
        CustomPool.min = min;
        CustomPool.max = max;
        CustomPool.threadName = threadName;
        init();
    }

    //指定大小的构造器
    public CustomPool(String threadName) {
        this(2, 10, threadName);
    }


    //线程池初始化方法,
    private void init() {
        //初始化大小
        for (int i = 0; i < min; i++) {
            createTask();
            //初始最小线程数
        }

        //调用自己的启动方法(线程池本身也是一个线程)
        this.start();

    }

    //创建线程
    public void createTask() {
        TaskThread taskThread = new TaskThread();
        //添加线程执行异常捕获
        taskThread.setUncaughtExceptionHandler((t, e) -> {
            System.out.println("线程:" + t.getName() + "出现异常! 内容为:" + e.toString());
        });
        //加入线程队列
        POOL.add(taskThread);
        //启动线程
        taskThread.start();
    }

    //设置添加任务的接口
    public void submit(Runnable runnable) {
        if (this.poolStatus == false) {
            throw new RuntimeException("线程池已经停止,无法提交新的任务");
        }
        synchronized (RUNNABLE_QUEUE) {
            RUNNABLE_QUEUE.offer(runnable);
            //唤醒在任务队列阻塞的线程
            RUNNABLE_QUEUE.notifyAll();
        }
    }

    //关闭线程(等待所有任务执行完成策略)
    public void shutDown() throws InterruptedException {
        synchronized (RUNNABLE_QUEUE){
            //如果任务队列不为空
            while (!RUNNABLE_QUEUE.isEmpty()) {
                //清空任务
                RUNNABLE_QUEUE.clear();
            }
            //拿出线程个数
            int threadNum = POOL.size();
            while (threadNum > 0) {
                Iterator<TaskThread> iterator = POOL.iterator();
                while (iterator.hasNext()) {
                    TaskThread next = iterator.next();
                    if (next.status == Status.BLOCKED ) {
                        //当线程处于阻塞状态的时候 尝试关闭线程
                        next.close();
                        iterator.remove();
                        System.out.println("线程 -1");
                        threadNum--;

                    }
                }
                Thread.sleep(100);
            }
            //关闭当前线程
            this.interrupt();
            Optional.of("线程池" + group.getName() + "已停止!").ifPresent(System.out::println);
        }


    }

    //定义一个私有内部类  用来执行该线程池的任务
    private class TaskThread extends Thread {
        //定义个状态  用来标记当前线程的运行状态
        private volatile Status status = Status.FREE;

        //构造器
        public TaskThread() {
            //调用父类构造,赋值
            super(group, threadName + (id++));
        }

        //关闭线程
        public void close() {
            //打断阻塞
            this.interrupt();
        }

        //重写run方法, 用于线程执行
        @Override
        public void run() {
            //循环   当前线程不是死亡的时候  就会一直在一个死循环中
            OUT:
            while (this.status != Status.DEAD) {
                Runnable runnable;
                //锁定任务队列,用线程安全的方式  取出其中一条任务
                synchronized (RUNNABLE_QUEUE) {
                    //当任务队列为空的时候
                    if (RUNNABLE_QUEUE.isEmpty()) {
                        try {
                            //当前线程进入阻塞状态
                            this.status = Status.BLOCKED;
                            //当前线程取出一个任务后,就转为等待状态
                            RUNNABLE_QUEUE.wait();
                        } catch (InterruptedException e) {
                            //当每次被唤醒的时候 跳到最外层 然后执行结束, 代表线程死亡
                            this.status = Status.DEAD;
                            break OUT;
                        }
                    }
                    //消费队列中最先进入的一条数据
                    runnable = RUNNABLE_QUEUE.poll();
                }
                //当任务部位空的时候就是可执行的时候了
                if (runnable != null) {
                    //在锁外部,执行各自的任务,将当前线程状态改为运行中
                    this.status = Status.RUNNING;
                    //运行任务
                    runnable.run();
                    //任务运行结束了 修改状态为运行完成就绪状态
                    this.status = Status.FREE;
                }
            }
            System.out.println(Thread.currentThread().getName() + " 线程关闭!!!");
        }


        //用来返回自定义的状态
        public Status getStatus() {
            return this.status;
        }
    }


    //定义枚举类 用来标注线程的状态
    public enum Status {
        /**
         * FREE: 就绪
         * RUNNING: 运行
         * BLOCKED: 阻塞
         * DEAD: 死亡
         */
        FREE, RUNNING, BLOCKED, DEAD;
    }


    //main 方法测试效果
    public static void main(String[] args) {
        CustomPool pool = new CustomPool("hhhhhhh");
        IntStream.range(0, 30).forEach(n -> {
            pool.submit(() -> {
                try {
                    Thread.sleep(1000);
                    System.out.println(Thread.currentThread().getName() + "   " + Thread.currentThread());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        });

        try {
            Thread.sleep(4000);
            pool.shutDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


}
